package com.ficus.road.maintain.service;

import com.ficus.road.maintain.client.Response.GetScoreDetailsResponse;
import com.ficus.road.maintain.client.Response.ManagementUnitResponse;
import com.ficus.road.maintain.core.model.Car;
import com.ficus.road.maintain.core.model.Company;
import com.ficus.road.maintain.core.model.RoadTypeEnum;
import com.ficus.road.maintain.core.model.Unit;
import com.ficus.road.maintain.core.model.zh.UnitScore;
import com.ficus.road.maintain.core.model.zh.UnitScoreDetail;
import com.ficus.road.maintain.core.model.zh.UnitScoreItem;
import com.ficus.road.maintain.core.model.zh.UnitScoreVo;
import com.ficus.road.maintain.dao.*;
import com.ficus.road.maintain.util.FormatUtil;
import com.ficus.road.maintain.util.MyDateUtil;
import com.google.common.base.Objects;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author jinbiao.he
 * @Since 2021/4/8 上午11:19
 */
@Service
@RequiredArgsConstructor
public class UnitService {
    private final UnitDao unitDao;
    private final CompanyDao companyDao;
    private final CarDao carDao;
    private final UnitScoreDao unitScoreDao;
    private final UnitScoreDetailDao unitScoreDetailDao;
    private Map<String, Unit> unitMap;

    @PostConstruct
    void init() {
        List<Unit> all = unitDao.findAll();
        unitMap = unitDao.findAll().stream().collect(Collectors.toMap(Unit::getId, item -> item));
    }

    public List<Unit> findByIds(List<String> ids) {
        Criteria criteria = Criteria.where("_id").in(ids);
        Query query = new Query(criteria);
        return unitDao.findByQuery(query);
    }

    public Car findCarById(String unitId) {
        Unit unit = unitDao.fetch(unitId);
        Company company = companyDao.findOne(new Query(Criteria.where("units").is(unitId)));
        Car car = carDao.findOne(new Query(Criteria.where("handle_company").is(company.getId())).skip(0).limit(1));
        return car;
    }

    public ManagementUnitResponse getUnitScoreRank() {
        //获取当前日
        int dayOfMonth = MyDateUtil.getDayOfMonth(new Date());
        String date = null;
        //如当前日在1日-19日之间，则取上上个月排行，否则取上月排行
        if (dayOfMonth>0&&dayOfMonth<=19){
            date = MyDateUtil.dateFormatStr(MyDateUtil.getFirstDayOfLastNMonth(2), "yyyy-MM");
        }else {
            date = MyDateUtil.dateFormatStr(MyDateUtil.getFirstDayOfLastMonth(), "yyyy-MM");
        }
        List<UnitScore> highwayList = unitScoreDao.findByQuery(new Query(Criteria.where("date").is(date).and("type").is(RoadTypeEnum.HIGHWAY.toString())).with(new Sort(Sort.Direction.ASC, "total")));
        List<UnitScore> highestThree = highwayList.stream()
                .sorted(Comparator.comparingDouble(UnitScore::getTotal).reversed())
                .limit(3)
                .collect(Collectors.toList());
        List<UnitScore> lowestThree = highwayList.stream()
                .sorted(Comparator.comparingDouble(UnitScore::getTotal))
                .limit(3)
                .collect(Collectors.toList());
        ManagementUnitResponse managementUnitResponse=new ManagementUnitResponse();
        List<GetScoreDetailsResponse> higList = new ArrayList<>();
        for (UnitScore getScoreDetailsResponse : highestThree) {
            GetScoreDetailsResponse getScore = new GetScoreDetailsResponse();
            String s = getScoreDetailsResponse.getUnitId();
            getScore.setUnitId(s);
            getScore.setUnitName(unitMap.get(s).getUnitName());
            getScore.setTotal(getScoreDetailsResponse.getTotal());
            higList.add(getScore);
        }
        List<GetScoreDetailsResponse> lowList = new ArrayList<>();
        for (UnitScore getScoreDetailsResponse : lowestThree) {
            GetScoreDetailsResponse getScore = new GetScoreDetailsResponse();
            String s = getScoreDetailsResponse.getUnitId();
            getScore.setUnitId(s);
            getScore.setUnitName(unitMap.get(s).getUnitName());
            getScore.setTotal(getScoreDetailsResponse.getTotal());
            lowList.add(getScore);
        }
        managementUnitResponse.setHighwayUnitScoreList(higList);
        managementUnitResponse.setRoadUnitScoreList(lowList);

        return managementUnitResponse;
    }

//    public UnitScoreVo getUnitScoreRank() {
//        String date = MyDateUtil.dateFormatStr(MyDateUtil.getFirstDayOfLastMonth(), "yyyy-MM");
//        List<UnitScore> highwayList = unitScoreDao.findByQuery(new Query(Criteria.where("date").is(date).and("type").is(RoadTypeEnum.HIGHWAY.toString())).with(new Sort(Sort.Direction.ASC, "total")));
//        List<UnitScoreVo.UnitScoreObject> highway = highwayList.stream()
//                .filter(item -> !ObjectUtils.isEmpty(unitMap.get(item.getUnitId())))
//                .filter(item -> !Objects.equal(0d, item.getTotal()))
//                .map(item -> UnitScoreVo.UnitScoreObject.builder()
//                        .unitId(item.getUnitId())
//                        .unitName(unitMap.get(item.getUnitId()).getUnitName())
//                        .total(item.getTotal())
//                        .build()).collect(Collectors.toList());
//        List<UnitScore> roadList = unitScoreDao.findByQuery(new Query(Criteria.where("date").is(date).and("type").is(RoadTypeEnum.ROAD.toString())).with(new Sort(Sort.Direction.ASC, "total")));
//        List<UnitScoreVo.UnitScoreObject> road = roadList.stream()
//                .filter(item -> !ObjectUtils.isEmpty(unitMap.get(item.getUnitId())))
//                .filter(item -> !Objects.equal(0d, item.getTotal()))
//                .map(item -> UnitScoreVo.UnitScoreObject.builder()
//                        .unitId(item.getUnitId())
//                        .unitName(unitMap.get(item.getUnitId()).getUnitName())
//                        .total(item.getTotal())
//                        .build()).collect(Collectors.toList());
//        UnitScoreVo res = UnitScoreVo.builder().roadUnitScoreList(road).highwayUnitScoreList(highway).build();
//        return res;
//    }
    public List<UnitScoreItem> getUnitScoreDetail(String unitId) {
        List<UnitScoreItem> res = new ArrayList<>();
        int dayOfMonth = MyDateUtil.getDayOfMonth(new Date());
        String date = null;
        //如当前日在1日-19日之间，则取上上个月排行，否则取上月排行
        if (dayOfMonth>0&&dayOfMonth<=19){
            date = MyDateUtil.dateFormatStr(MyDateUtil.getFirstDayOfLastNMonth(2), "yyyy-MM");
        }else {
            date = MyDateUtil.dateFormatStr(MyDateUtil.getFirstDayOfLastMonth(), "yyyy-MM");
        }
        List<UnitScoreDetail> details = unitScoreDetailDao.findByQuery(new Query(Criteria.where("date").is(date).and("unit_id").is(unitId)));
        Map<String, List<UnitScoreDetail>> map = details.stream().collect(Collectors.groupingBy(item -> getUnitScoreGroupId(item.getSecondProject())));
        map.forEach((groupId, list) -> {
            UnitScoreItem unitScoreItem = new UnitScoreItem();
            List<UnitScoreItem.UnitScoreItemDetail> itemDetails = new ArrayList<>();
            double totalScore;
            if (Objects.equal(groupId, "null")) {
                return;
            } else {
                list.forEach(item -> {
                    UnitScoreItem.UnitScoreItemDetail detail = UnitScoreItem.UnitScoreItemDetail.builder()
                            .secondProject(item.getSecondProject())
                            .scoreStandard(item.getScoreStandard())
                            .fullMarks(item.getFullMarks())
                            .score(item.getScore())
                            .deductReason(item.getDeductScoreReason())
                            .build();
                    itemDetails.add(detail);
                });
                totalScore = list.stream().mapToDouble(UnitScoreDetail::getScore).sum();
            }
            if (Objects.equal("规范化管理", groupId)) {
                totalScore = FormatUtil.keepDecimalsOfK(totalScore * 0.4, 1);
            } else if (Objects.equal("智能管理", groupId)) {
                totalScore = FormatUtil.keepDecimalsOfK(totalScore * 0.6, 1);
            }
            unitScoreItem.setFirstProject(groupId);
            unitScoreItem.setDetails(itemDetails);
            unitScoreItem.setTotalScore(totalScore);
            res.add(unitScoreItem);
        });
        return res;
    }

    private String getUnitScoreGroupId(String projectName) {
        if (StringUtils.isEmpty(projectName)) {
            return "null";
        }
        String groupId;
        switch (projectName) {
            case "清扫保洁":
            case "绿化养护":
            case "路面养护":
            case "桥梁养护":
            case "附属设施":
            case "内业资料":
            case "安全文明":
            case "道班房管理":
            case "路政管理":
            case "排水养护":
            case "规范作业":
            case "监控督察":
                groupId = "规范化管理";
                break;
            case "智能发现":
            case "路况检测":
            case "机扫GPS":
            case "桥检打卡":
            case "诉求处置":
                groupId = "智能管理";
                break;
            case "行业及属地检查":
            case "媒体曝光上级监督":
            case "重大安全生产事故":
            case "抗灾不力":
                groupId = "专项扣分";
                break;
            case "规范化管理":
            case "智能管理":
            case "专项扣分":
            default:
                groupId = "null";
        }
        return groupId;
    }
}
